package com.db.bankapp.domain;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.*;

/**
 * @ThreadSafe
 * Blocking Queue implementation
 * @param <T>
 */
class BlockingQueue<T> implements Queue<T> {
    // @GuardedBy(lock)
    private final List<T> queue = new LinkedList<>();
    private final Lock lock = new ReentrantLock();
    private final Condition elementAdded = lock.newCondition();

    // todo: add blocking on size preset
    @Override
    public void add(T object) throws InterruptedException {
        lock.lock();
        try {
            queue.add(object);
            elementAdded.signalAll();
        } finally {
            lock.unlock();
        }
    }

    @Override
    public T remove() throws InterruptedException {
        lock.lock();
        try {
            while(queue.isEmpty()) {
                try {
                    elementAdded.await();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    throw e;
                }
            }
            return queue.remove(0);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public boolean isEmpty() {
        lock.lock();
        try {
            return queue.isEmpty();
        } finally {
            lock.unlock();
        }
    }
}
